package com.xingda.packing.plc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.xingda.packing.appset.AppSetService;
import com.xingda.packing.minitor.entity.PkPlcLog;
import com.xingda.packing.minitor.mapper.PkPlcLogMapper;
import com.xingda.packing.plc.entity.PlcItem;
import com.xingda.packing.plc.entity.PlcItemVal;
import com.xingda.packing.plc.service.PlcDirectiveService;
import com.xingda.packing.plc.service.PlcHandleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * PLC发送指令实现类
 *
 * @author LEGION
 */
@Slf4j
@Component
public class PlcDirectiveServiceImpl implements PlcDirectiveService {
    @Resource
    private PkPlcLogMapper pkPlcLogMapper;
    @Resource
    private PlcHandleService plcHandleService;

    @Resource
    private AppSetService appSetService;

    /**
     * 去起始位抓取
     *
     * @param locationNo 起始点
     * @param area       区域
     */
    @Override
    public void goZeroGrab(int locationNo, int area) {

//        测试用
        log.info("====测试-goZeroGrab");

        wheelGrabLocation(area, locationNo);
        trigger(area);
//        taskLocation(area, 1);
//        allowTask(area);
//        resetPalletizingState(area);
//        resetGrabState(area);
//        mesSuccess(area);
//        region 抓取起始位抓取任务下发

//        List<PlcItemVal> pivList = new ArrayList<>();
//        pivList.add(new PlcItemVal("工字轮抓取位置号", getFieldQuery("GZLZQWZH", area), locationNo));
//        pivList.add(new PlcItemVal("触发", getFieldQuery("CF", area), false));
//        pivList.add(new PlcItemVal("任务位置", getFieldQuery("RWWZ", area), 1));
//        pivList.add(new PlcItemVal("允许下发任务", getFieldQuery("YXXFRW", area), false));
//        pivList.add(new PlcItemVal("机器人抓取完成", getFieldQuery("JQRZQWC", area), false));
//        pivList.add(new PlcItemVal("机器人码垛完成", getFieldQuery("JQRMDWC", area), false));
//        pivList.add(new PlcItemVal("MES下发任务完成", getFieldQuery("MESXFRWWC", area), true));
//        log.info("前往传送带抓取位抓取任务下发成功-抓取位：{},区域{}", locationNo, area);
//        if (!plcHandleService.writeItem(pivList)) {
//            log.error("前往传送带抓取位抓取任务下发失败-抓取位：{},区域{}", locationNo, area);
//        }
//        log.info("PLC写入信息{}", pivList);

//        endregion
    }

//    位置顺序修改  左右中
    public void wheelGrabLocation(int area, int location) {
        if (area == 1) {
            writeVals(new PlcItemVal("工字轮抓取位置号", "%DB2000.DBW838.0:INT", location));
        } else if (area == 2) {
            writeVals(new PlcItemVal("工字轮抓取位置号", "%DB2000.DBW1430.0:INT", location));
        } else if (area == 3){
            writeVals(new PlcItemVal("工字轮抓取位置号", "%DB2000.DBW1134.0:INT", location));
        }
    }


    public void trigger(int area) {
        if (area == 1) {
            writeVals(new PlcItemVal("触发", "%DB2000.DBX824.1:BOOL", false));
        } else if (area == 2) {
            writeVals(new PlcItemVal("触发", "", false));
        } else if (area == 3){
            writeVals(new PlcItemVal("触发", "%DB2000.DBX1120.1:BOOL", false));
        }
    }


    /**
     * 抓取起始位放置缓存位
     *
     * @param wheelTypeCode 工字轮类型GDL
     * @param cacheLocation 缓存位编号
     * @param area          区域
     */
    @Override
    public void startStorage(int wheelTypeCode, int cacheLocation, int area) {
        // 放缓存位置号
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("缓存台码垛位置号", getFieldQuery("HCTMDWZH", area), cacheLocation));
        pivList.add(new PlcItemVal("100产品类别", getFieldQuery("100CPLB", area), wheelTypeCode));
        pivList.add(new PlcItemVal("任务位置", getFieldQuery("RWWZ", area), 3));
        pivList.add(new PlcItemVal("允许下发任务", getFieldQuery("YXXFRW", area), false));
        pivList.add(new PlcItemVal("机器人抓取完成", getFieldQuery("JQRZQWC", area), false));
        pivList.add(new PlcItemVal("机器人码垛完成", getFieldQuery("JQRMDWC", area), false));
        pivList.add(new PlcItemVal("MES下发任务完成", getFieldQuery("MESXFRWWC", area), true));
        log.info("抓取位存放缓存位任务下发成功,工字轮类型:{},缓存位编号:{},区域:{}", wheelTypeCode, cacheLocation, area);
        if (!plcHandleService.writeItem(pivList)) {
            log.error("存放缓存位任务下发失败-缓存位：{}", cacheLocation);
        }
        log.info("PLC写入信息{}", pivList);
    }

    /**
     * 抓取起始位放装箱位
     *
     * @param wheelTypeCode 工字轮类型
     * @param boxLocationNo 装箱位编号
     * @param area          区域
     */
    @Override
    public void startGrab(int wheelTypeCode, int boxLocationNo, int area) {
        // 给机器人发指令 托盘号
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("托盘号", getFieldQuery("TPH", area), boxLocationNo));
        pivList.add(new PlcItemVal("100产品类别", getFieldQuery("100CPLB", area), wheelTypeCode));
        pivList.add(new PlcItemVal("任务位置", getFieldQuery("RWWZ", area), 2));
        pivList.add(new PlcItemVal("允许下发任务", getFieldQuery("YXXFRW", area), false));
        pivList.add(new PlcItemVal("机器人抓取完成", getFieldQuery("JQRZQWC", area), false));
        pivList.add(new PlcItemVal("机器人码垛完成", getFieldQuery("JQRMDWC", area), false));
        pivList.add(new PlcItemVal("MES下发任务完成", getFieldQuery("MESXFRWWC", area), true));
        log.info("抓取位存放装箱位任务下发成功,码垛托盘号:{},工字轮类型:{},区域:{}", wheelTypeCode, boxLocationNo, area);
        if (!plcHandleService.writeItem(pivList)) {
            log.error("存放装箱位任务下发失败-码垛托盘号：{}", boxLocationNo);
        }
        log.info("PLC写入信息{}", pivList);
    }

    /**
     * 抓取缓存位放装箱位
     *
     * @param cacheLocationNo 缓存位置编号
     * @param boxLocationNo   装箱位编号
     * @param productType     产品类型
     * @param wheelNo         条形码
     * @param area            区域
     */
    @Override
    public void startCacheGrab(int cacheLocationNo, int boxLocationNo, int productType, String wheelNo, int area) {
        if (productType == -1 || productType == 0) {
            log.error("产品类型出错：{}", productType);
            return;
        }
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("工字轮抓取位置号", getFieldQuery("GZLZQWZH", area), cacheLocationNo));
        pivList.add(new PlcItemVal("托盘号", getFieldQuery("TPH", area), boxLocationNo));
        pivList.add(new PlcItemVal("100产品类别", getFieldQuery("100CPLB", area), productType));
        pivList.add(new PlcItemVal("任务位置", getFieldQuery("RWWZ", area), 4));
        pivList.add(new PlcItemVal("允许下发任务", getFieldQuery("YXXFRW", area), false));
        pivList.add(new PlcItemVal("机器人抓取完成", getFieldQuery("JQRZQWC", area), false));
        pivList.add(new PlcItemVal("机器人码垛完成", getFieldQuery("JQRMDWC", area), false));
        char[] wheelNos = wheelNo.toCharArray();
        if (wheelNos.length <= 20) {
            int length = wheelNos.length;
            for (int i = 0; i < length; i++) {
                int no = wheelNos[i];
                int num = i + 1;
                String key = "code" + num;
                PlcItemVal piv = new PlcItemVal(key, getFieldQuery(key, area), no);
                pivList.add(piv);
            }
        }
        pivList.add(new PlcItemVal("MES下发任务完成", getFieldQuery("MESXFRWWC", area), true));
        boolean result = plcHandleService.writeItem(pivList);
        if (result) {
            log.info("抓取缓存位放装箱位成功,缓存位:{},装箱位:{},产品类型:{},条形码:{},区域:{}", cacheLocationNo, boxLocationNo, productType, wheelNo, area);
        }
        if (!result) {
            log.error("存放缓存位任务下发失败-缓存位：{}，装箱位{}", cacheLocationNo, boxLocationNo);
        }
        log.info("PLC写入信息{}", pivList);
    }

    /**
     * 轮号接受完成
     *
     * @param productType 产品类别
     * @param area        区域
     */
    @Override
    public void receive(int productType, int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("100产品类别", getFieldQuery("100CPLB", area), productType));
        pivList.add(new PlcItemVal("触发", getFieldQuery("CF", area), false));
        pivList.add(new PlcItemVal("MES解析完成", getFieldQuery("MESJXWC", area), true));
        plcHandleService.writeItem(pivList);
        log.info("轮号接收完成,产品类别{},区域{}", productType, area);
        log.info("PLC写入信息{}", pivList);
    }

    /**
     * 条形码读取触发
     *
     * @param area 区域
     * @return 触发完成
     */
    @Override
    public boolean isScanSignal(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("触发", getFieldQuery("CF", area)));
        // 正在循环、触发为true ，轮号接受完成为false
        return json.getBooleanValue("触发");
    }

    /**
     * 查询码垛完成情况
     *
     * @param area 区域
     */
    @Override
    public boolean isPalletizingComplete(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("机器人码垛完成", getFieldQuery("JQRMDWC", area)));
        log.info("查询码垛完成情况:{}", json.getBooleanValue("机器人码垛完成"));
        return json.getBooleanValue("机器人码垛完成");
    }

    /**
     * 重置码垛完成
     *
     * @param area 区域
     */
    @Override
    public void resetPalletizingState(int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("机器人码垛完成", getFieldQuery("JQRMDWC", area), false));
        plcHandleService.writeItem(pivList);
        log.info("PLC写入信息{}", pivList);
    }

    /**
     * 重置抓取完成
     *
     * @param area 区域
     */
    @Override
    public void resetGrabState(int area) {

//        左右中顺序
         if (area == 1) {
            writeVals(new PlcItemVal("机器人码垛完成", "%DB2000.DBX824.2:BOOL", false));
        } else if (area == 3) {
            writeVals(new PlcItemVal("机器人码垛完成", "%DB2000.DBX1120.2:BOOL", false));
        } else if (area == 2){
            writeVals(new PlcItemVal("机器人码垛完成", "%DB2000.DBX1416.2:BOOL", false));
        }

//        旧代码
//        List<PlcItemVal> pivList = new ArrayList<>();
//        pivList.add(new PlcItemVal("机器人抓取完成", getFieldQuery("JQRZQWC", area), false));
//        plcHandleService.writeItem(pivList);
//        log.info("PLC写入信息{}", pivList);
    }

    /**
     * 查询抓取完成
     *
     * @param area 区域
     */
    @Override
    public boolean isGrabComplete(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("机器人抓取完成", getFieldQuery("JQRZQWC", area)));
        log.info("机器人抓取完成:" + json.getBooleanValue("机器人抓取完成"));
        return json.getBooleanValue("机器人抓取完成");
    }

    /**
     * 查询是否运行下发任务
     *
     * @param area 区域
     */
    @Override
    public boolean canAssignTask(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("允许下发任务", getFieldQuery("YXXFRW", area)));
        return json.getBooleanValue("允许下发任务");
    }

    /**
     * 抓取位读码
     *
     * @param area 区域
     */
    @Override
    public String getScanWheelNo(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("条码", getFieldQuery("TXM", area)));
        return json.getString("条码");
    }

    @Override
    public boolean clearCacheLocationNo(int locationNo, int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("缓存位位置号", getFieldQuery("SCHCH", area), locationNo));
        pivList.add(new PlcItemVal("删除缓存", getFieldQuery("SCHC", area), true));
        boolean result = plcHandleService.writeItem(pivList);
        if (result) {
            log.info("删除缓存位删除成功,缓存位置号:{},区域:{}", locationNo, area);
            pkPlcLogMapper.insert(new PkPlcLog(area, pivList.toString(), new Date()));
            return true;
        }
        log.error("删除缓存位删除失败,缓存位置号:{},区域:{}", locationNo, area);
        return false;
    }

    @Override
    public void resetCacheStatus(int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("删除缓存", getFieldQuery("SCHC", area), false));
        plcHandleService.writeItem(pivList);
        pkPlcLogMapper.insert(new PkPlcLog(area, pivList.toString(), new Date()));
    }

    private String getFieldQuery(String key) {
        return appSetService.getPlcNodes().getJSONObject(key).getString("address");
    }

    private String getFieldQuery(String key, int area) {
        if (area == 1) {
            return appSetService.getPlcNodes().getJSONObject(key).getString("address1");
        } else if (area == 2) {
            return appSetService.getPlcNodes().getJSONObject(key).getString("address2");
        } else if (area == 3) {
            return appSetService.getPlcNodes().getJSONObject(key).getString("address1");
        } else {
            return appSetService.getPlcNodes().getJSONObject(key).getString("address2");
        }
    }

    @Override
    public void writeVals(PlcItemVal... plcItemVals) {
        boolean result = plcHandleService.writeItem(plcItemVals);
        if (!result) {
            log.error("初始设置装箱位失败！");
        }
    }

    @Override
    public boolean isTrue(String address) {
        JSONObject json = plcHandleService.readItem(new PlcItem("isTrue", address));
        return json.getBooleanValue("isTrue");
    }

    @Override
    public JSONObject readVals(PlcItem... plcItems) {
        return plcHandleService.readItem(plcItems);
    }

    @Override
    public JSONObject readVals(List<PlcItem> plcItems) {
        PlcItem[] pi = new PlcItem[plcItems.size()];
        plcItems.toArray(pi);
        return readVals(pi);
    }

    @Override
    public boolean isPhotoFinish(String address) {
        JSONObject json = plcHandleService.readItem(new PlcItem("拍照完成", address));
        return json.getBooleanValue("拍照完成");
    }

    @Override
    public boolean is100HaveWheel(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("100抓取位有轮", getFieldQuery("100ZQWSFYL", area)));
        return json.getBooleanValue("100抓取位有轮");
    }

    @Override
    public boolean is101HaveWheel(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("101抓取位有轮", getFieldQuery("101ZQWSFYL", area)));
        return json.getBooleanValue("101抓取位有轮");
    }

    @Override
    public boolean getRobotStatus(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("强制停止机器人", getFieldQuery("QZTZJQR", area)));
        return json.getBooleanValue("强制停止机器人");
    }

    @Override
    public boolean isShuntAreaSignal(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("触发MES解析条码", getFieldQuery("FLQCFTMJX", area)));
        return json.getBooleanValue("触发MES解析条码");
    }

    @Override
    public boolean isSnapSignal(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("触发MES解析卡扣", getFieldQuery("FLQCFKKJX", area)));
        return json.getBooleanValue("触发MES解析卡扣");
    }

    @Override
    public String getShuntAreaScanWheelNo(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("分流区条码", getFieldQuery("FLQTXM", area)));
        return json.getString("分流区条码");
    }


    @Override
    public void writeValueToShuntArea(int location, String code, int area) {
        log.info("区域:{},条码{}", location, code);
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("分流区域", getFieldQuery("FLQY", area), location));
//        char[] wheelNos = code.toCharArray();
//        if (wheelNos.length <= 20) {
//            int length = wheelNos.length;
//            for (int i = 0; i < length; i++) {
//                int no = wheelNos[i];
//                int num = i + 1;
//                String key = "MESJXCTM" + num;
//                PlcItemVal piv = new PlcItemVal(key, getFieldQuery(key, area), no);
//                pivList.add(piv);
//            }
//        }
        boolean result = plcHandleService.writeItem(pivList);
        //pkPlcLogMapper.insert(new PkPlcLog(3, pivList.toString(), new Date()));
        if (!result) {
            log.error("分流区域写入失败!区域:{},条码:{}", area, code);
        }
    }

    @Override
    public boolean isShuntOver(int area) {
        JSONObject json = plcHandleService.readItem(new PlcItem("分流完成", getFieldQuery("FLQFLWC", area)));
        return json.getBooleanValue("分流完成");
    }

    @Override
    public void restartShuntAreaSignal(int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal("分流完成", getFieldQuery("FLQFLWC", area), false));
        boolean result = plcHandleService.writeItem(pivList);
        pkPlcLogMapper.insert(new PkPlcLog(3, pivList.toString(), new Date()));
        if (!result) {
            log.error("分流区重置失败");
        }
    }

    @Override
    public int getProductTypeToShunt(int area) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("高低轮", getFieldQuery("FLQGDL", area)));
        return jsonObject.getIntValue("高低轮");
    }

    @Override
    public int getProductTypeToZeroGrab(int area, int locationNo) {
        if (locationNo == 100) {
            return plcHandleService.readItem(new PlcItem("100高低轮", getFieldQuery("100GDL", area))).getIntValue("100高低轮");
        } else {
            return plcHandleService.readItem(new PlcItem("101高低轮", getFieldQuery("101GDL", area))).getIntValue("101高低轮");
        }
    }

    @Override
    public int getProductType(int area) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("100产品类别", getFieldQuery("100CPLB", area)));
        return jsonObject.getIntValue("100产品类别");
    }

    @Override
    public int getPalletPackingCount(String address) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("count", address));
        return jsonObject.getIntValue("count");
    }

    @Override
    public int getPalletWheelNumSet(String address) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("num", address));
        return jsonObject.getIntValue("num");
    }

    @Override
    public boolean getMesTask(int area) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("MES下发任务完成", getFieldQuery("MESXFRWWC", area)));
        return jsonObject.getBooleanValue("MES下发任务完成");
    }

    @Override
    public int getTaskType(int area) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("任务位置", getFieldQuery("RWWZ", area)));
        return jsonObject.getIntValue("任务位置");
    }

    @Override
    public void grabWheel(int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal(new PlcItem("任务位置", getFieldQuery("RWWZ", area)), 5));
        plcHandleService.writeItem(pivList);
        pkPlcLogMapper.insert(new PkPlcLog(area, pivList.toString(), new Date()));
    }

    @Override
    public boolean getPlcStatus() {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("MES心跳", getFieldQuery("MESXT")));
        return jsonObject.getBooleanValue("MES心跳");
    }

    @Override
    public void writePlcStatus() {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal(new PlcItem("MES心跳", getFieldQuery("MESXT")), false));
        plcHandleService.writeItem(pivList);
        pkPlcLogMapper.insert(new PkPlcLog(3, pivList.toString(), new Date()));
    }

    @Override
    public void codeParsingSucceeded(int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal(new PlcItem("触发MES解析条码", getFieldQuery("FLQCFTMJX", area)), false));
        pivList.add(new PlcItemVal(new PlcItem("MES解析条码完成", getFieldQuery("FLQJXTMWC", area)), true));
        plcHandleService.writeItem(pivList);
        pkPlcLogMapper.insert(new PkPlcLog(3, pivList.toString(), new Date()));
    }

    @Override
    public void codeParsingFailed(int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal(new PlcItem("触发MES解析条码", getFieldQuery("FLQCFTMJX", area)), false));
        pivList.add(new PlcItemVal(new PlcItem("MES解析条码错误", getFieldQuery("FLQJXTMCW", area)), true));
        plcHandleService.writeItem(pivList);
        pkPlcLogMapper.insert(new PkPlcLog(3, pivList.toString(), new Date()));
    }

    @Override
    public void snapParsingSucceeded(int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal(new PlcItem("触发MES解析卡扣", getFieldQuery("FLQCFKKJX", area)), false));
        pivList.add(new PlcItemVal(new PlcItem("MES解析卡扣完成", getFieldQuery("FLQKKJXWC", area)), true));
        plcHandleService.writeItem(pivList);
        pkPlcLogMapper.insert(new PkPlcLog(3, pivList.toString(), new Date()));
    }

    @Override
    public void snapParsingFailed(int area) {
        List<PlcItemVal> pivList = new ArrayList<>();
        pivList.add(new PlcItemVal(new PlcItem("触发MES解析卡扣", getFieldQuery("FLQCFKKJX", area)), false));
        pivList.add(new PlcItemVal(new PlcItem("MES解析卡扣错误", getFieldQuery("FLQKKJXCW", area)), true));
        plcHandleService.writeItem(pivList);
        pkPlcLogMapper.insert(new PkPlcLog(3, pivList.toString(), new Date()));
    }

    @Override
    public boolean isCodeParsingSucceeded(int area) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("MES解析条码完成", getFieldQuery("FLQJXTMWC", area)));
        return jsonObject.getBooleanValue("MES解析条码完成");
    }

    @Override
    public boolean isCodeParsingFailed(int area) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("MES解析条码错误", getFieldQuery("FLQJXTMCW", area)));
        return jsonObject.getBooleanValue("MES解析条码错误");
    }

    @Override
    public boolean isSnapParsingSucceeded(int area) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("MES解析卡扣完成", getFieldQuery("FLQKKJXWC", area)));
        return jsonObject.getBooleanValue("MES解析卡扣完成");
    }

    @Override
    public boolean isSnapParsingFailed(int area) {
        JSONObject jsonObject = plcHandleService.readItem(new PlcItem("MES解析卡扣错误", getFieldQuery("FLQKKJXCW", area)));
        return jsonObject.getBooleanValue("MES解析卡扣错误");
    }

}
